package cc.ufinity.networkdiagnose.manager;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;

import android.util.Log;
/**
 * FTP测试类
 * @author ZR
 *
 */
public final class FtpTestManager extends AbstractManager{

	private static final int DEFAULT_CONNECT_TIMEOUT = 6000;
	protected FTPClient ftpClient;
	private String localFilePath;
	private String remoteFilePath;
	private String fileName;
	private long fileSize;
	private long loginTime;
	public int failedTimes;

	public long getLoginTime() {
		return loginTime;
	}

	public long getFileSize() {
		return fileSize;
	}

	public void setFileSize(long fileSize) {
		this.fileSize = fileSize;
	}

	private int frequency = 0;// 测试频率

	private boolean testing;

	public boolean isTesting() {
		return testing;
	}

	public void setTesting(boolean testing) {
		this.testing = testing;
	}

	public int getFrequency() {
		return frequency;
	}

	public int currentTimes;// 当前测试次数

	public int getCurrentTimes() {
		return currentTimes;
	}

	private double[] upX = null;// 绘制上传报表X轴数据

	public double[] getUpX() {
		return upX;
	}

	private double[] upY = null;// 绘制上传报表Y轴数据

	public double[] getUpY() {
		return upY;
	}

	private double[] dwX = null;

	public double[] getDwX() {
		return dwX;
	}

	private double[] dwY = null;

	public double[] getDwY() {
		return dwY;
	}

	private float currentUpSpeed = 0;
	private float currentDwSpeed = 0;
	private float totalDwSpeed = 0;
	private float totalUpSpeed = 0;

	public FtpTestManager(final String localFilePath,
			final String remoteFilePath, final String fileName) {
		this.fileName = fileName;
		this.localFilePath = localFilePath;
		this.remoteFilePath = remoteFilePath;
		ftpClient = new FTPClient();
	}


	public void startFtpUpTest(final int frequency) {
		this.frequency = frequency;
		upX = new double[frequency];
		upY = new double[frequency];

		while (currentTimes < frequency) {
			// 进行上传测试
			if (!testing) {
				setTesting(true);
				currentUpSpeed = upload();
				// setTestData();
				upX[currentTimes] = currentTimes;
				upY[currentTimes] = currentUpSpeed;
				this.setTotalUpSpeed(currentUpSpeed);
				currentTimes++;
				sendMsg(MessageWhat.FTP_UPLOAD_DONE);
			}

		}
	}

	public void startFtpDwTest(final int frequency) {
		currentTimes = 0;
		setTesting(false);
		dwX = new double[frequency];
		dwY = new double[frequency];
		while (currentTimes < frequency) {
			// 进行下载测试
			if (!testing) {
				setTesting(true);
				currentDwSpeed = download();
				// setTestData();
				dwX[currentTimes] = currentTimes;
				dwY[currentTimes] = currentDwSpeed;
				this.setTotalDwSpeed(currentDwSpeed);
				currentTimes++;
				// 一次轮询测试结束通知界面刷新数据
				sendMsg(MessageWhat.FTP_DOWNLOAD_DONE);
			}

		}

		// 通知界面测试结束
		sendMsg(MessageWhat.DONE);
	}

	public void logout() {
		try {
			ftpClient.disconnect();
		} catch (IOException e) {
			Log.e("FTP Logout", "FTP退出认证出错：", e);
		}
	}

	public boolean login(final String address, final int port,
			final String user, final String pwd) {
		boolean result = false;
		try {
			long start  =System.currentTimeMillis();
			ftpClient.connect(address, port);
			boolean loginResult = ftpClient.login(user, pwd);
			int returnCode = ftpClient.getReplyCode();
			if (loginResult && FTPReply.isPositiveCompletion(returnCode)) {
				initRemote();
				result = true;
				loginTime = System.currentTimeMillis() - start;
			}
		} catch (Exception e) {
			Log.e("FTP Login", "FTP登陆认证出错：", e);
		}
		return result;
	}

	private void initRemote() throws IOException {
		ftpClient.makeDirectory(remoteFilePath);
		ftpClient.changeWorkingDirectory(remoteFilePath);
		ftpClient.setBufferSize(1024);
		ftpClient.setControlEncoding("UTF-8");
		ftpClient.enterLocalPassiveMode();
		ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
		ftpClient.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT);
	}
	
	// FTP 上传文件测试
	public void upload(String fileName) {
		FileInputStream fis = null;
		try {
			fis = new FileInputStream(localFilePath + fileName);
			ftpClient.storeFile(fileName, fis);
		} catch (IOException e) {
			Log.e("FTP Upload", "FTP上传文件出错：", e);
		} finally {
			try {
				if (null != fis) {
					fis.close();
				}
			} catch (IOException e) {
				// ignore
			}
		}
	}

	// FTP 上传文件测试
	public float upload() {
		FileInputStream fis = null;
		float speed = 0;
		try {
			fis = new FileInputStream(localFilePath + fileName);
			long start = System.currentTimeMillis();
			ftpClient.storeFile(fileName, fis);
			long time = System.currentTimeMillis() - start;
			speed = ((float) fileSize/1024)/((float)time/1000);
		} catch (IOException e) {
			Log.e("FTP Upload", "FTP上传文件出错：", e);
			return -1;
		} finally {
			try {
				if (null != fis) {
					fis.close();
				}
			} catch (IOException e) {
				// ignore
			}
		}
		return speed;
	}

	// FTP下载测试
	public float download() {
		File file = new File(localFilePath + fileName);
		if (file.exists()) {
			file.delete();
		}
		float speed = 0;
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(file);
			long start = System.currentTimeMillis();
			ftpClient.retrieveFile(fileName, fos);
			long time = System.currentTimeMillis() - start;
			speed = ((float) fileSize/1024)/((float)time/1000);
		} catch (Exception e) {
			Log.e("FTP Download", "FTP下载测试出错：", e);
		} finally {
			try {
				if (null != fos) {
					fos.close();
				}
			} catch (IOException e1) {
				// ignore
			}
		}
		return speed;
	}

	public float getCurrentUpSpeed() {
		return currentUpSpeed;
	}

	public float getCurrentDwSpeed() {
		return currentDwSpeed;
	}

	public float getTotalUpSpeed() {
		return totalUpSpeed;
	}

	public void setTotalUpSpeed(float totalUpSpeed) {
		this.totalUpSpeed += totalUpSpeed;
	}

	public float getTotalDwSpeed() {
		return totalDwSpeed;
	}

	public void setTotalDwSpeed(float totalDwSpeed) {
		this.totalDwSpeed += totalDwSpeed;
	}

}
